package com.godyao.framework.beans.factory.support;

import com.godyao.framework.beans.BeansException;
import com.godyao.framework.beans.factory.DisposableBean;
import com.godyao.framework.beans.factory.factory.SingletonBeanRegistry;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

/**
 * 获取单例对象实现类
 * 给子类提供添加单例对象的方法
 * @author missw
 */
public abstract class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {
    /**
     *空单例对象的内部标记
     *  used as marker value for concurrent Maps (which don't support null values)
     */
    protected static final Object NULL_OBJECT = new Object();
    /**
     * 注册的有销毁方法的Bean
     */
    private final Map<String, DisposableBean> disposableBeans = new LinkedHashMap<>();
    /**
     * 单例对象容器
     */
    private Map<String, Object> singletonObjects = new HashMap<>();

    @Override
    public Object getSingleton(String beanName) {
        return singletonObjects.get(beanName);
    }

    @Override
    public void registerSingleton(String beanName, Object singletonObject) {
        singletonObjects.put(beanName, singletonObject);
    }

    protected void registerDisposableBean(String beanName, DisposableBean bean) {
        disposableBeans.put(beanName, bean);
    }

    /**
     * 销毁Bean
     * @param beanName
     */
    public void destroySingleton(String beanName) {
        DisposableBean disposableBean = disposableBeans.remove(beanName);
        if (null != disposableBean) {
            try {
                disposableBean.destroy();
            } catch (Exception e) {
                throw new BeansException("Destroy method on bean with name '" + beanName + "' threw an Exception", e);
            }
        }
    }

    /**
     * 销毁所有Bean
     */
    public void destroySingletons(){
        Set<String> beanNames = disposableBeans.keySet();
        Object[] disposableBeanNames = beanNames.toArray();

        // 从后往前销毁
//        for (String beanName : beanNames) {
//            destroySingleton(beanName);
//        }
        for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
            String disposableBeanName = (String)disposableBeanNames[i];
            destroySingleton(disposableBeanName);

        }
    }


}
